package com.atguigu.tms.mock.service.impl;


import com.atguigu.mock.util.DijkstraUtil;
import com.atguigu.mock.util.LineInfo;
import com.atguigu.mock.util.RandomNum;
import com.atguigu.tms.mock.bean.ATemplateCityDistance;
import com.atguigu.tms.mock.bean.BaseOrgan;
import com.atguigu.tms.mock.bean.LineBaseInfo;
import com.atguigu.tms.mock.config.AppConfig;
import com.atguigu.tms.mock.constant.TmsConstant;
import com.atguigu.tms.mock.mapper.LineBaseInfoMapper;
import com.atguigu.tms.mock.service.ATemplateCityDistanceService;
import com.atguigu.tms.mock.service.BaseOrganService;
import com.atguigu.tms.mock.service.LineBaseInfoService;
import com.atguigu.tms.mock.service.adv.impl.AdvServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 线路基本表 服务实现类
 * </p>
 *
 * @author zhangchen
 * @since 2022-03-20
 */
@Service
@Slf4j
public class LineBaseInfoServiceImpl extends AdvServiceImpl<LineBaseInfoMapper, LineBaseInfo> implements LineBaseInfoService {

    @Autowired
    BaseOrganService baseOrganService;

    @Autowired
    ATemplateCityDistanceService aTemplateCityDistanceService;



    ArrayList<LineInfo> lineInfoDistanceList=new ArrayList<>();
    ArrayList<LineInfo> lineInfoTimeList=new ArrayList<>();
    ArrayList<LineInfo> lineInfoCostList=new ArrayList<>();

    public void initLineInfoList( ){
        Map<Long, LineBaseInfo> lineBaseInfoMap = cache;
        lineInfoDistanceList.clear();
        lineInfoTimeList.clear();
        lineInfoCostList.clear();
        for (LineBaseInfo lineBaseInfo : lineBaseInfoMap.values()) {
            lineInfoDistanceList.add(new LineInfo(lineBaseInfo.getId(),
                    lineBaseInfo.getStartOrgId().toString(),
                    lineBaseInfo.getEndOrgId().toString(),
                    lineBaseInfo.getDistance().intValue()));
            lineInfoTimeList.add(new LineInfo(lineBaseInfo.getId(),
                    lineBaseInfo.getStartOrgId().toString(),
                    lineBaseInfo.getEndOrgId().toString(),
                    lineBaseInfo.getEstimatedTime().intValue()));
            lineInfoCostList.add(new LineInfo(lineBaseInfo.getId(),
                    lineBaseInfo.getStartOrgId().toString(),
                    lineBaseInfo.getEndOrgId().toString(),
                    lineBaseInfo.getCost().intValue()));
        }


    }


    @Override
    public void loadCache() {
        super.loadCache();
        initLineInfoList();
    }

    public Long  caleLineInfoDistance(Long startDistrictId, Long endDistrictId   ){
        Long distance=0L;

        List<LineInfo> lineInfoList = calcLineInfo(startDistrictId, endDistrictId);

        for (LineInfo lineInfo : lineInfoList) {
            LineBaseInfo lineBaseInfo = getById(lineInfo.getId(), true);
            distance+= lineBaseInfo.getDistance().longValue();
        }
        return  distance;

    }


    public  List<LineInfo>  calcLineInfo(Long startDistrictId,Long endDistrictId ){

        BaseOrgan startOrgan = baseOrganService.getOrganByRegionId(startDistrictId);
        BaseOrgan endOrgan = baseOrganService.getOrganByRegionId(endDistrictId);

        String startOrgId=startOrgan.getId().toString();
        String endOrgId=endOrgan.getId().toString();

        String planStrategy="";
        if(AppConfig.default_plan_strategy.equals("1")){
            planStrategy=TmsConstant.PLAN_STRATEGY_DISTANCE;
        }else if (AppConfig.default_plan_strategy.equals("2")){
            planStrategy=TmsConstant.PLAN_STRATEGY_TIME;
        } else if (AppConfig.default_plan_strategy.equals("3")) {
            planStrategy=TmsConstant.PLAN_STRATEGY_COST;
        }


        DijkstraUtil dijkstraUtil=new DijkstraUtil();
        List<LineInfo> lineInfoList=null;
        if(planStrategy.equals(TmsConstant.PLAN_STRATEGY_DISTANCE)){
            ArrayList<LineInfo> lineInfoArrayList = (ArrayList<LineInfo>)lineInfoDistanceList.clone();
            lineInfoList= dijkstraUtil.routePlanning(startOrgId,endOrgId,lineInfoArrayList);
        }else if(planStrategy.equals(TmsConstant.PLAN_STRATEGY_TIME)){
            ArrayList<LineInfo> lineInfoArrayList = (ArrayList<LineInfo>)lineInfoTimeList.clone();
            lineInfoList= dijkstraUtil.routePlanning(startOrgId,endOrgId,lineInfoArrayList);
        }else if(planStrategy.equals(TmsConstant.PLAN_STRATEGY_COST)){
            ArrayList<LineInfo> lineInfoArrayList = (ArrayList<LineInfo>)lineInfoCostList.clone();
            lineInfoList=   dijkstraUtil.routePlanning(startOrgId,endOrgId,lineInfoArrayList);
        }

        return lineInfoList;

    }



    public void initLineBaseInfo(){
        Integer lineNo=100001;
        log.info("---初始化运输线路  ----");
        log.info("---生成二级站点线路  ----");
        // 连接所有二级站点到一级站点
        List<BaseOrgan> baseOrganL2List = baseOrganService.list(new QueryWrapper<BaseOrgan>().eq("org_level", 2));

        for (BaseOrgan baseOrganL2 : baseOrganL2List) {
            Long orgParentId = baseOrganL2.getOrgParentId();
            BaseOrgan baseOrganL1 = baseOrganService.getById(orgParentId, true);
            LineBaseInfo lineBaseInfo = new LineBaseInfo();

            lineBaseInfo.setLineNo("G"+lineNo++ +"B" );
            int dist = RandomNum.getRandInt(30, 70);
            lineBaseInfo.setDistance(BigDecimal.valueOf(dist));
            BigDecimal costFactor =  BigDecimal.valueOf (  RandomNum.getRandInt(100, 130)).divide(BigDecimal.valueOf(100),1, RoundingMode.HALF_UP);


            lineBaseInfo.setCost(BigDecimal.valueOf(dist).multiply(costFactor) );
            BigDecimal trafficJamFactor =  BigDecimal.valueOf (  RandomNum.getRandInt(70, 90)).divide(BigDecimal.valueOf(100),1, RoundingMode.HALF_UP);

            lineBaseInfo.setEstimatedTime(lineBaseInfo.getDistance().multiply(trafficJamFactor).intValue()  );

            lineBaseInfo.setOrgId(baseOrganL1.getId());

            lineBaseInfo.setStartOrgId(baseOrganL2.getId());
            lineBaseInfo.setStartOrgName(baseOrganL2.getOrgName());

            lineBaseInfo.setEndOrgId(baseOrganL1.getId());
            lineBaseInfo.setEndOrgName(baseOrganL1.getOrgName());



             lineBaseInfo.setLineLevel(2);


            lineBaseInfo.setCreateTime(AppConfig.mock_date);

            lineBaseInfo.setTransportLineTypeId(TmsConstant.TRANSPORT_TYPE_ROAD);
            lineBaseInfo.setName(lineBaseInfo.getStartOrgName()+" 至 "+lineBaseInfo.getEndOrgName());

             saveOrUpdate(lineBaseInfo,true);

            //
            LineBaseInfo lineBaseInfoBack = new LineBaseInfo();
            try {
                BeanUtils.copyProperties(lineBaseInfoBack,lineBaseInfo);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            lineBaseInfoBack.setLineNo("G"+lineNo+"F"  );
            String orgTmpName=lineBaseInfo.getEndOrgName();
            Long orgTmpId=lineBaseInfo.getEndOrgId();

            lineBaseInfoBack.setOrgId(baseOrganL1.getId());

            lineBaseInfoBack.setEndOrgName(lineBaseInfo.getStartOrgName());
            lineBaseInfoBack.setEndOrgId(lineBaseInfo.getStartOrgId());

            lineBaseInfoBack.setStartOrgName (orgTmpName);
            lineBaseInfoBack.setStartOrgId(orgTmpId);

            lineBaseInfoBack.setName(lineBaseInfoBack.getStartOrgName()+" 至 "+lineBaseInfoBack.getEndOrgName());
            lineBaseInfoBack.setPairLineId(lineBaseInfo.getId());
            lineBaseInfoBack.setId(null);

            saveOrUpdate(lineBaseInfoBack,true);

            lineBaseInfo.setPairLineId(lineBaseInfoBack.getId());
            saveOrUpdate(lineBaseInfo,true);




        }

        log.info("---生成一级站点线路  ----");
        Map<Long, ATemplateCityDistance> aTemplateCityDistanceMap = aTemplateCityDistanceService.all(true);
        for (ATemplateCityDistance templateCityDistance : aTemplateCityDistanceMap.values()) {
            BaseOrgan baseOrgan1 = baseOrganService.getOrganByRegionId(templateCityDistance.getCityNo1());
            BaseOrgan baseOrgan2 = baseOrganService.getOrganByRegionId(templateCityDistance.getCityNo2());

            LineBaseInfo lineBaseInfo = new LineBaseInfo();
            lineBaseInfo.setOrgId(baseOrgan1.getId());
            lineBaseInfo.setLineNo("S"+lineNo++  );
            lineBaseInfo.setDistance(BigDecimal.valueOf(templateCityDistance.getDistance()));
            lineBaseInfo.setStartOrgName(baseOrgan1.getOrgName());
            lineBaseInfo.setStartOrgId(baseOrgan1.getId());
            lineBaseInfo.setEndOrgName(baseOrgan2.getOrgName());
            lineBaseInfo.setEndOrgId(baseOrgan2.getId());
            lineBaseInfo.setDistance(BigDecimal.valueOf(templateCityDistance.getDistance()));

            BigDecimal costFactor =  BigDecimal.valueOf (  RandomNum.getRandInt(150, 180)).divide(BigDecimal.valueOf(100),2, RoundingMode.HALF_UP);

            lineBaseInfo.setCost( lineBaseInfo.getDistance().multiply(costFactor) );
            BigDecimal trafficJamFactor =  BigDecimal.valueOf (  RandomNum.getRandInt(50, 60)).divide(BigDecimal.valueOf(100),1, RoundingMode.HALF_UP);

            lineBaseInfo.setEstimatedTime(lineBaseInfo.getDistance().multiply(trafficJamFactor).intValue()  );

            lineBaseInfo.setName(lineBaseInfo.getStartOrgName()+" 至 "+lineBaseInfo.getEndOrgName());

            lineBaseInfo.setCreateTime(AppConfig.mock_date);

            lineBaseInfo.setTransportLineTypeId(TmsConstant.TRANSPORT_TYPE_ROAD);

            lineBaseInfo.setLineLevel(1);

             saveOrUpdate(lineBaseInfo,true);


            //反向路线
            LineBaseInfo lineBaseInfoB = new LineBaseInfo();
            try {
                BeanUtils.copyProperties(lineBaseInfoB,lineBaseInfo);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }


            lineBaseInfoB.setLineNo("S"+lineNo+"R"  );

            lineBaseInfoB.setEndOrgName(lineBaseInfo.getStartOrgName());
            lineBaseInfoB.setEndOrgId(lineBaseInfo.getStartOrgId());

            lineBaseInfoB.setStartOrgName (lineBaseInfo.getEndOrgName());
            lineBaseInfoB.setStartOrgId(lineBaseInfo.getEndOrgId());

            lineBaseInfoB.setName(lineBaseInfo.getStartOrgName()+" 至 "+lineBaseInfo.getEndOrgName());
            lineBaseInfoB.setId(null);
            lineBaseInfoB.setPairLineId(lineBaseInfo.getId());
            saveOrUpdate(lineBaseInfoB,true);
            lineBaseInfo.setPairLineId(lineBaseInfoB.getId());
            saveOrUpdate(lineBaseInfo,true);

        }

        initLineInfoList();
    }
}
